﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using WorkFlowCore.Authorization;
using WorkFlowCore.Common.SimplePluginLoaders;
using WorkFlowCore.Conditions;
using WorkFlowCore.Framework.Authorization;
using WorkFlowCore.Framework.Conditions;
using WorkFlowCore.Framework.EventHandlers;
using WorkFlowCore.Framework.Repositories;
using WorkFlowCore.Framework.Repositories4EF;
using WorkFlowCore.Framework.UserSelectors;
using WorkFlowCore.IRepositories;
using WorkFlowCore.UserSelectors;
using WorkFlowCore.Workflows;
using WorkFlowCore.WorkTasks;

namespace WorkFlowCore.Framework
{
    public static class WorkFlowCoreFrameworkService
    {
        /// <summary>
        /// orm类型，目前暂时只支持本地文件，后续考虑增加 Ef 、sqlsuger 的支持
        /// </summary>
        public enum FrameworkConfigOrmType
        {
            Default,
            EF,
        }
        public class FrameworkConfig
        {
            public FrameworkConfigOrmType OrmType { get; set; } = FrameworkConfigOrmType.Default;
        }
        public static void AddWorkFlowCoreFramework(this IServiceCollection services,Action<FrameworkConfig> config=null)
        {
            var conf = new FrameworkConfig();
            config?.Invoke(conf);
            if (conf.OrmType== FrameworkConfigOrmType.Default)
            {
                services.AddScoped(typeof(IBasicRepository<,>), typeof(BasicRepository<,>));
                services.AddScoped(typeof(IBasicRepository<>), typeof(BasicRepository<>));
                services.AddScoped(typeof(IWorkStepRepository), typeof(WorkStepRepository));
                services.AddScoped(typeof(IWorkTaskRepository), typeof(WorkTaskRepository));
                services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork));
                services.AddScoped(typeof(UnitOfWork));
                services.AddScoped(typeof(IUnitOfWorkManager), typeof(UnitOfWorkManager));
            }
            else if (conf.OrmType == FrameworkConfigOrmType.EF)
            {
                services.AddScoped(typeof(IBasicRepository<,>), typeof(BasicRepository4EF<,>));
                services.AddScoped(typeof(IBasicRepository<>), typeof(BasicRepository4EF<>));
                services.AddScoped(typeof(IWorkStepRepository), typeof(WorkStepRepository4EF));
                services.AddScoped(typeof(IWorkTaskRepository), typeof(WorkTaskRepository4EF));
                services.AddScoped(typeof(IUnitOfWork), typeof(UnitOfWork4EF));
                services.AddScoped(typeof(IUnitOfWorkManager), typeof(UnitOfWorkManager4EF));
            }

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            //事件处理
            services.AddScoped<SendTaskEventHandler>();
            services.AddScoped<TaskFinishedEventHandler>();
            services.AddScoped<AutoHandleStepsEventHandler>();

            var assembly = typeof(WorkFlowCoreFrameworkService).Assembly;
            services.Replace(new ServiceDescriptor(typeof(IWorkflowSession),typeof(DefaultSession), ServiceLifetime.Scoped));

            //注册条件和选择器
            #region 注册条件和选择器
            UserSelectorManager.RegisterSelector(services, assembly);
            services.LoadPlugins(Path.Combine(AppContext.BaseDirectory, "Plugins", "UserSelectors"), plugins =>
            {
                UserSelectorManager.RegisterSelector(services, plugins.Select(p => p.Assembly).ToArray());

            });
            ConditionManager.Registercondition(services, assembly);

            services.LoadPlugins(Path.Combine(AppContext.BaseDirectory, "Plugins", "Conditions"), plugins =>
            {
                ConditionManager.Registercondition(services, plugins.Select(p => p.Assembly).ToArray());
            });
            #endregion


            //services.AddScoped<ConditionA>();
            //services.AddScoped<GeneralCondition>();
            //services.AddScoped<UserSelectorA>();
            //services.AddScoped<UserSelectorB>();
            //services.AddScoped<UserSelectorAllUsers>();
        }
    }
}
